package com.hbx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbx.auth.AuthCacheService;
import com.hbx.constant.CachePrefixContent;
import com.hbx.constant.DateFormatContent;
import com.hbx.constant.FeedbackEnum;
import com.hbx.constant.TableEnum;
import com.hbx.logs.annotation.MarkLog;
import com.hbx.logs.OperaTypeEnum;
import com.hbx.dto.feedback.AddFeedbackDto;
import com.hbx.dto.feedback.FeedBackHandlerDto;
import com.hbx.dto.feedback.SearchListDto;
import com.hbx.exception.RspException;
import com.hbx.model.Feedback;
import com.hbx.mapper.FeedbackMapper;
import com.hbx.model.Notice;
import com.hbx.model.User;
import com.hbx.service.FeedbackService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbx.service.NoticeService;
import com.hbx.service.UserService;
import com.hbx.task.CompletableFutureService;
import com.hbx.utils.CacheUtils;
import com.hbx.utils.DateUtil;
import com.hbx.utils.MailSendUtil;
import com.hbx.utils.Result;
import com.hbx.vo.PageBean;
import com.hbx.vo.PublicUserVo;
import com.hbx.vo.feedback.FeedbackListVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.mail.MessagingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hbx
 * @since 2022-01-29
 */
@Service
@Slf4j
public class FeedbackServiceImpl extends ServiceImpl<FeedbackMapper, Feedback> implements FeedbackService {

    @Autowired
    private FeedbackMapper feedbackMapper;

    @Autowired
    private CacheUtils cacheUtils;

    @Autowired
    private CompletableFutureService completableFutureService;

    @Autowired
    private NoticeService noticeService;

    @Autowired
    private MailSendUtil mailSendUtil;

    @Autowired
    private UserService userService;

    /**
     * 获取反馈类型
     * @param r
     */
    @Override
    public void getType(Result r) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (FeedbackEnum anEnum : FeedbackEnum.values()) {
            Map<String,Object> map = new HashMap<>();
            map.put("id",anEnum.getId());
            map.put("type",anEnum.getType());
            list.add(map);
        }
        r.setCode(200).setData(list);
    }

    /**
     * 新增反馈
     * @param dto
     * @param r
     */
    @Override
    public void addFeedback(AddFeedbackDto dto, Result r) {
        Feedback feedback = new Feedback();
        User user = AuthCacheService.getUser();
        Set<Object> members = cacheUtils.getSetMembers(CachePrefixContent.PLAT_FEEDBACK_INFO + user.getUserId());
        if (!CollectionUtils.isEmpty(members) && members.size() >= 3){
            r.setCode(201).setMsg("反馈失败,今日次数已超过最大限制");
            return;
        }
        BeanUtils.copyProperties(dto, feedback);
        feedback.setFeedbackDate(new Date());
        feedback.setFeedbackType(FeedbackEnum.getType(dto.getFeedbackType()));
        feedback.setFeedbackUserId(user.getUserId());
        int insert = feedbackMapper.insert(feedback);
        if (insert == 1){
            r.setCode(200).setMsg("反馈成功,请留意邮箱");
            // redis存信息
            cacheUtils.add(CachePrefixContent.PLAT_FEEDBACK_INFO + user.getUserId(), new Object[]{feedback.getId()});
            // 发邮件通知
            completableFutureService.runAsyncTask(() -> {
                QueryWrapper<Notice> wrapper = new QueryWrapper<>();
                wrapper.eq("is_delete", 0);
                List<Notice> noticeList = noticeService.list(wrapper);
                if (!CollectionUtils.isEmpty(noticeList)){
                    StringBuilder sb = new StringBuilder();
                    sb.append("<div>反馈类型:");
                    sb.append(FeedbackEnum.getType(dto.getFeedbackType()));
                    sb.append("</div>");
                    sb.append("<div>反馈内容:");
                    sb.append(dto.getFeedbackContent());
                    sb.append("</div>");
                    String subject = "系统收到一封反馈信息,请及时处理!";
                    List<String> strings = noticeList.stream().map(Notice::getNoticeEmail).collect(Collectors.toList());
                    try {
                        mailSendUtil.send(subject, strings.toArray(new String[0]), sb.toString());
                    } catch (MessagingException e) {
                        e.printStackTrace();
                        log.error("【反馈模块】:邮件发送失败");
                    }
                }
            });
            return;
        }
        r.setCode(201).setMsg("反馈失败");
    }

    /**
     * 获得反馈列表
     * @param dto
     * @param r
     */
    @Override
    public void getFeedbackListPage(SearchListDto dto, Result r) {
        PageBean pageBean = new PageBean();
        Page<Feedback> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Integer status = dto.getFeedbackStatus();
        String feedbackType = dto.getFeedbackType();
        String keyword = dto.getKeyword();
        QueryWrapper<Feedback> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("feedback_status").orderByAsc("feedback_date");
        if (status != null){
            wrapper.eq("feedback_status",status);
        }
        if (StringUtils.hasLength(feedbackType)){
            wrapper.like("feedback_type",feedbackType);
        }
        if (StringUtils.hasLength(keyword)){
            wrapper.like("feedback_type",keyword)
                    .or().like("feedback_content", keyword)
                    .or().like("feedback_result", keyword);
        }

        IPage<Feedback> iPage = feedbackMapper.selectPage(page, wrapper);
        pageBean.setTotal(iPage.getTotal());
        pageBean.setPageNum(iPage.getCurrent());
        pageBean.setPageSize(iPage.getSize());

        List<Feedback> records = iPage.getRecords();
        if (CollectionUtils.isEmpty(records)){
            r.setCode(200).setData(pageBean);
            return;
        }
        List<FeedbackListVo> list = new ArrayList<>();
        records.stream().forEach(record -> {
            FeedbackListVo vo = new FeedbackListVo();
            BeanUtils.copyProperties(record, vo);
            Integer userId = record.getFeedbackUserId();
            if (userId != null){
                User feedbackUser = userService.getById(userId);
                if (feedbackUser != null){
                    PublicUserVo userVo = new PublicUserVo();
                    userVo.setUserId(feedbackUser.getUserId());
                    userVo.setUserName(feedbackUser.getLoginName());
                    userVo.setAvatar(feedbackUser.getAvator());
                    userVo.setType(feedbackUser.getType());
                    vo.setFeedbackUser(userVo);
                }
            }
            Integer adminId = record.getHandlerAdmin();
            if (adminId != null){
                User adminUser = userService.getById(adminId);
                if (adminUser != null){
                    PublicUserVo userVo = new PublicUserVo();
                    userVo.setUserId(adminUser.getUserId());
                    userVo.setUserName(adminUser.getLoginName());
                    userVo.setAvatar(adminUser.getAvator());
                    userVo.setType(adminUser.getType());
                    vo.setHandlerAdmin(userVo);
                }
            }
            list.add(vo);
        });
        pageBean.setData(list);
        r.setCode(200).setData(pageBean);
    }

    /**
     * 处理反馈
     * @param dto
     * @param r
     */
    @Override
    @MarkLog(operate = OperaTypeEnum.UPDATE, tables = TableEnum.FEEDBACK, desc = "管理员处理反馈")
    public void handlerFeedback(FeedBackHandlerDto dto, Result r) {
        User user = AuthCacheService.getUser();
        Integer id = dto.getId();
        Integer feedBackHandlerCode = dto.getFeedBackHandlerCode();
        String feedBackHandlerResult = dto.getFeedBackHandlerResult();
        Feedback feedback = feedbackMapper.selectById(id);
        if (feedback == null){
            r.setCode(201).setMsg("反馈消息不存在");
            return;
        }
        if (feedBackHandlerCode.equals(1)){
            // 直接处理
            feedbackHandler(user, id, feedBackHandlerResult);
        }else if (feedBackHandlerCode.equals(2)){
            // 处理并反馈
            feedbackHandler(user, id, feedBackHandlerResult);
            // 反馈
            String subject = "反馈处理完成,请查看..";
            String content = "用户您好,你与" + DateUtil.dateToString(feedback.getFeedbackDate(), DateFormatContent.YYYY_MM_DD_HH_MM_SS) + "提交的反馈已处理,请及时查看!";
            User feedbackUser = userService.getById(feedback.getFeedbackUserId());
            if (feedbackUser != null){
                completableFutureService.runAsyncTask(() -> {
                    try {
                        mailSendUtil.send(subject, new String[]{feedbackUser.getEmail()}, content);
                    } catch (MessagingException e) {
                        e.printStackTrace();
                        log.error("【反馈模块】:反馈处理完成,通知反馈人邮件发送失败");
                    }
                });
            }
        } else{
            r.setCode(200).setMsg("处理方式暂不支持");
            return;
        }
        r.setCode(200).setMsg("处理成功");
    }

    /**
     * 获取反馈详情
     * @param id
     * @param r
     */
    @Override
    public void getFeedbackDetail(Integer id, Result r) {
        Feedback feedback = feedbackMapper.selectById(id);
        if (feedback == null){
            r.setCode(201).setMsg("反馈消息不存在");
            return;
        }

        FeedbackListVo vo = new FeedbackListVo();
        BeanUtils.copyProperties(feedback, vo);
        Integer userId = feedback.getFeedbackUserId();
        if (userId != null){
            User feedbackUser = userService.getById(userId);
            if (feedbackUser != null){
                PublicUserVo userVo = new PublicUserVo();
                userVo.setUserId(feedbackUser.getUserId());
                userVo.setUserName(feedbackUser.getLoginName());
                userVo.setAvatar(feedbackUser.getAvator());
                userVo.setType(feedbackUser.getType());
                vo.setFeedbackUser(userVo);
            }
        }
        Integer adminId = feedback.getHandlerAdmin();
        if (adminId != null){
            User adminUser = userService.getById(adminId);
            if (adminUser != null){
                PublicUserVo userVo = new PublicUserVo();
                userVo.setUserId(adminUser.getUserId());
                userVo.setUserName(adminUser.getLoginName());
                userVo.setAvatar(adminUser.getAvator());
                userVo.setType(adminUser.getType());
                vo.setHandlerAdmin(userVo);
            }
        }
        r.setCode(200).setData(vo);
    }

    /**
     * 获得我的反馈列表
     * @param r
     */
    @Override
    public void getMyFeedbackList(Result r) {
        User user = AuthCacheService.getUser();
        QueryWrapper<Feedback> wrapper = new QueryWrapper<>();
        wrapper.eq("feedback_user_id",user.getUserId())
                .orderByAsc("feedback_status")
                .orderByAsc("feedback_date");
        List<Feedback> feedbacks = feedbackMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(feedbacks)){
            r.setCode(200).setData(feedbacks);
            return;
        }
        List<FeedbackListVo> list = new ArrayList<>();
        feedbacks.stream().forEach(record -> {
            FeedbackListVo vo = new FeedbackListVo();
            BeanUtils.copyProperties(record, vo);
            Integer adminId = record.getHandlerAdmin();
            if (adminId != null){
                User adminUser = userService.getById(adminId);
                if (adminUser != null){
                    PublicUserVo userVo = new PublicUserVo();
                    userVo.setUserId(adminUser.getUserId());
                    userVo.setUserName(adminUser.getLoginName());
                    userVo.setAvatar(adminUser.getAvator());
                    userVo.setType(adminUser.getType());
                    vo.setHandlerAdmin(userVo);
                }
            }
            list.add(vo);
        });
        r.setCode(200).setData(list);
    }

    /**
     * 处理反馈
     * @param user
     * @param id
     * @param feedBackHandlerResult
     */
    private void feedbackHandler(User user, Integer id, String feedBackHandlerResult) {
        Feedback back = new Feedback();
        back.setId(id);
        back.setFeedbackResult(feedBackHandlerResult);
        back.setHandlerAdmin(user.getUserId());
        back.setFeedbackStatus(1);
        int result = feedbackMapper.updateById(back);
        if (result != 1){
            throw new RspException(201,"处理失败");
        }
    }
}
